let isa = {};

let oinit = [
  { class: 'Sword', ISA: [ 'Weapon' ], ch: ')' , name: 'a sword' },
  { class: 'Shield', ISA: [ 'Armor' ], ch: ')' , name: 'a shield' },
  { class: 'Wand', ISA: [ 'Wand' ], ch: '/' , name: 'a wand' },
  { class: 'Potion', ISA: [ 'Potion' ], ch: '!' , name: 'a potion' },
  { class: 'Food', ISA: [ 'Food' ], ch: '%' , name: 'a food unit' },
  { class: 'Ash', ISA: [ 'Misc' ], ch: '~' , name: 'a pile of ash' },

  /*
   * Abstract base classes
   */
  { class: 'Weapon', ISA: [ 'Obj' ] },
  { class: 'Armor', ISA: [ 'Obj' ] },
  { class: 'Potion', ISA: [ 'Obj' ] },
  { class: 'Wand', ISA: [ 'Obj' ] },
  { class: 'Food', ISA: [ 'Obj' ] },
  { class: 'Misc', ISA: [ 'Obj' ] },
]


/*
 * I want to be able to say:
 *
 * if (obj.isa('Sword')) { ...
 * if (obj.isa(Obj.Sword)) { ...
 * if (Obj.Sword.isa('Weapon') { ...
 * sword = new Sword()
 */

for each (let init in oinit) {
  let class = init.class;
  let einit = 'function ' + class + '() {};' + 
       class + '.prototype = new Obj();';
  eval(einit);
  for (let i in init) { 
    einit = class + '.prototype["' + i + '"] = "' + init[i] + '";';
    eval(einit);
  }
  for (let c in init.ISA) {
    if (isa[class] == null) {
      isa[class] = [ c ];
    } else {
      isa[class].push(c);
    }
  }
  let class_init = 'var ' + class + ' = new Class("' + class + '"';
  if (init.ISA == null) {
    class_init += ');'
  } else {
    class_init += ', [';
    for each (let c in init.ISA) {
      class_init += c.name + ', ';
    }
    class_init += ']);';
  }
  eval(class_init);
//  var Obj = new Class('Obj');
//  var Weapon = new Class('Weapon', [ Obj ]);
//  var Sword = new Class('Sword', [ Weapon ]);

}

function Class(name, isa) {
  this.name = name;
  this.isa = isa;
}

Class.prototype.isa = function(what) {
  if (this.class == what) { return true; }
  if (this.isa == null) { return false; }
  for each (let c in this.isa) {
    if (c.isa(what)) { return true; }
  }
  return false;
}

Obj.prototype.place_at = function(x, y) {
  if (this.x == x && this.y == y) {
    return;
  }
  if (G.map.is_on(this.x, this.y)) {
    G.level.set_obj_at(this.x, this.y, null);
    G.map.set_dirty(this.x, this.y);
  }
  if (G.map.is_on(x, y)) {
    G.level.set_obj_at(x, y, this);
    G.map.set_dirty(x, y);
    this.x = x;
    this.y = y;
  }
 // update_map();
  update_screen_backing();
  update_screen();
}

Obj.prototype.pick_up = function(cr) {
  if (cr.invent.length > 0) {
    more("You're already carrying something.");
    return;
  }
  if (G.map.is_on(this.x, this.y)) {
    G.level.set_obj_at(this.x, this.y, null);
    cr.invent.push(this);
    more('You picked up ' + this.name + '.');
    this.x = -1;
    this.y = -1;
  }
//  update_map();
  update_screen_backing();
  update_screen();
}

Obj.prototype.drop = function(x, y) {
  var cr;
  if (!(cr = G.level.cr_at(x, y))) {
    more("For some reason, there's nothing here to drop this object.");
    return;
  }
  if (G.level.obj_at(x, y)) {
    more("Something's already here.");
    return;
  }
  cr.invent.pop();
  G.level.set_obj_at(x, y, this);
  this.x = x;
  this.y = y;
  G.map.update_cell(x, y);
  more("You dropped " + this.name + ".");
}

function Obj(init) {
  for (let p in init) { this[p] = init[p]; }
  this.x = -1;
  this.y = -1;
}

